#ifndef GNTARRAY_H
#define GNTARRAY_H

#include "GnTCollection.h"

template <class T, class TAlloc>
class GnTArray : public GnMemoryObject
{
public:
	// construction and destruction
	GnTArray(gtuint uiMaxSize = 0, gtuint uiGrowBy = 1);
	virtual ~GnTArray();

	// Number of slots used in array, including zeroed items.
	// Use this number to iterate over all items in array, (some may be 0)
	gtuint GetSize() const;

	// Number of non-zero items in array, less or equal to GetSize()
	gtuint GetEffectiveSize() const;

	gtuint GetAllocatedSize() const;
	gtuint GetGrowBy() const;
	void SetSize(gtuint uiSize);
	void SetGrowBy(gtuint uiGrowBy);

	// set and get elements
	T* GetBase();
	const T& GetAt(gtuint uiIndex) const;
	T& GetAt(gtuint uiIndex);
	void SetAt(gtuint uiIndex, const T& element);
	gtuint SetAtGrow(gtuint uiIndex, const T& element);

	// add and remove elements
	gtuint Add(const T& element);
	gtuint AddFirstEmpty(const T& element);
	T RemoveAt(gtuint uiIndex);
	// Removes last element in array and places it at uiIndex
	T RemoveAtAndFill(gtuint uiIndex);
	T RemoveEnd();
	void RemoveAll();

	// Remove the first found occurrence of the specified element.  If the
	// element is not T(0) and is in the array, the array slot is set to T(0)
	// and its index is returned.  If the element is T(0) or not in the array,
	// the maximum gtuint is returned ((gtuint)~0).  NOTE:  If
	// the element occurs multiple times in the array, only the first
	// occurrence is removed.
	gtuint Remove(const T& element);

	// Compact all elements to contiguous space starting at the beginning of
	// the array.  Reallocation is performed to eliminate unused slots.
	void Compact();

	// After deletions before mSize slot, mSize no longer points to
	// the first available slot.  This routine resets it to the first
	// available slot.
	void UpdateSize();

protected:
	T* m_pBase;                // pointer to the array storage
	gtuint mMaxSize;  // number of slots in array
	gtuint mSize;     // first available empty slot in array
	gtuint mESize;    // number of filled slots
	gtuint mGrowBy;   // number of slots to grow array when full

private:
	// To prevent an application from inadvertently causing the compiler to
	// generate the default copy constructor or default assignment operator,
	// these methods are declared as private. They are not defined anywhere,
	// so code that attempts to use them will not link.
	GnTArray(const GnTArray&);
	GnTArray& operator=(const GnTArray&);
};

template <class T>
class GnTObjectArray : public GnTArray<T, GnTNewInterface<T> >
{
public:
	GnTObjectArray(gtuint uiMaxSize = 0, gtuint uiGrowBy = 1);
};

template <class T>
class GnTPrimitiveArray : public GnTArray<T, GnTMallocInterface<T> >
{
public:
	GnTPrimitiveArray(gtuint uiMaxSize = 0,
		gtuint uiGrowBy = 1);
};

#include "GnTArray.inl"
#endif // GNTARRAY_H
